home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / ds5000.md / devSmem.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  13KB  |  420 lines

  1. /* 
  2.  * devSmem.c --
  3.  *
  4.  *    Stubs to implement /dev/smem.  Allow reading and writing
  5.  *      to kernel memory.
  6.  *
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #ifndef lint
  13. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/ds5000.md/devSmem.c,v 1.1 92/08/13 15:53:37 secor Exp $ SPRITE (Berkeley)";
  14. #endif not lint
  15.  
  16. #include "sprite.h"
  17. #include "fs.h"
  18. #include <vmPmaxConst.h>
  19. #include <dbg.h>
  20. #define NOGAP
  21.  
  22. static char smemBuf[1024];
  23. extern int vm_PageSize;
  24. extern int mach_KernStackSize;
  25. extern int vmBlockCacheEndAddr;
  26. extern int vmBlockCacheBaseAddr;
  27. extern int vmStackEndAddr;
  28. extern int vmStackBaseAddr;
  29. extern int vmMemEnd;
  30. extern int vmBootEnd;
  31. extern int mach_KernStart;
  32. extern int mach_CodeStart;
  33. extern Mach_DebugState mach_DebugState;
  34. static void     DebugToRegState _ARGS_((Mach_DebugState *debugPtr,
  35.                         Mach_RegState *regPtr));
  36.  
  37.  
  38. /*
  39.  *----------------------------------------------------------------------
  40.  *
  41.  *  Dev_SmemRead --
  42.  *
  43.  *    Return number of bytes read and SUCCESS if nonzero bytes returned.
  44.  *
  45.  * Results:
  46.  *    A standard Sprite return status.
  47.  *
  48.  * Side effects:
  49.  *    None.
  50.  *
  51.  *----------------------------------------------------------------------
  52.  */
  53. /*ARGSUSED*/
  54. ReturnStatus
  55. Dev_SmemRead(devicePtr, readPtr, replyPtr)
  56.     Fs_Device *devicePtr;
  57.     Fs_IOParam    *readPtr;    /* Read parameter block */
  58.     Fs_IOReply    *replyPtr;    /* Return length and signal */ 
  59. {
  60.   int status, bytesLeft;
  61.   int kernelAddress;
  62.   int numPages, bytesInPage;
  63.   char *bufPtr;
  64.   StopInfo stopInfo;
  65.   Dbg_DumpBounds currentBounds;
  66.   
  67.   stopInfo.codeStart = (int)mach_CodeStart;
  68.   stopInfo.trapType = (mach_DebugState.causeReg & MACH_CR_EXC_CODE) >>
  69.     MACH_CR_EXC_CODE_SHIFT;
  70.   DebugToRegState(&mach_DebugState, &(stopInfo.regs));
  71.   currentBounds.pageSize = vm_PageSize;
  72.   currentBounds.stackSize = mach_KernStackSize;
  73.   currentBounds.kernelCodeStart = (unsigned int) mach_KernStart;
  74.   currentBounds.kernelCodeSize  =
  75.     (unsigned int) (vmBootEnd - mach_KernStart);
  76.   currentBounds.kernelDataStart  = VMMACH_VIRT_CACHED_START;
  77.   currentBounds.kernelDataSize   = (unsigned int)
  78.     (vmMemEnd - VMMACH_VIRT_CACHED_START);
  79.   currentBounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  80.   currentBounds.kernelStacksSize = (unsigned int)
  81.     (vmStackEndAddr - vmStackBaseAddr);
  82.   currentBounds.fileCacheStart   = (unsigned int)vmBlockCacheBaseAddr;
  83.   currentBounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr -
  84.                         vmBlockCacheBaseAddr);
  85.   kernelAddress = readPtr->offset;
  86.   bytesLeft = readPtr->length;
  87.   bufPtr = readPtr->buffer;
  88.   if (kernelAddress < sizeof(StopInfo)) {
  89.     if (bytesLeft + kernelAddress <= sizeof(StopInfo)) {
  90.       bcopy(((char *)&stopInfo) + kernelAddress, readPtr->buffer, readPtr->length);
  91.       replyPtr->length = readPtr->length;
  92.       return(SUCCESS);
  93.     }
  94.     bcopy(((char *)&stopInfo) + kernelAddress, readPtr->buffer, sizeof(StopInfo) - kernelAddress);
  95.     bytesLeft -= sizeof(StopInfo) - kernelAddress;
  96.     bufPtr += sizeof(StopInfo) - kernelAddress;
  97.     kernelAddress = sizeof(StopInfo);
  98.   }
  99.   if (kernelAddress < (sizeof(StopInfo) + sizeof(Dbg_DumpBounds))) {
  100.     if (bytesLeft + kernelAddress <= sizeof(StopInfo) + sizeof(Dbg_DumpBounds)) {
  101.       bcopy(((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bufPtr, bytesLeft);
  102.       replyPtr->length = readPtr->length;
  103.       return(SUCCESS);
  104.     }
  105.     bcopy(((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bufPtr, sizeof(Dbg_DumpBounds));
  106.     bytesLeft -= sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  107.     bufPtr += sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  108.     kernelAddress = mach_KernStart;
  109.   }
  110.   kernelAddress += mach_KernStart - (sizeof(StopInfo) + sizeof(Dbg_DumpBounds));
  111. #ifdef NOGAP
  112.   if (kernelAddress > vmBootEnd) {
  113.     kernelAddress += VMMACH_VIRT_CACHED_START - vmBootEnd;
  114.   }
  115.   if (kernelAddress > vmMemEnd) {
  116.     kernelAddress += vmStackBaseAddr - vmMemEnd;
  117.   }
  118.   if (kernelAddress > vmStackEndAddr) {
  119.     kernelAddress += vmBlockCacheBaseAddr - vmStackEndAddr;
  120.   }
  121.   if (kernelAddress > vmBlockCacheEndAddr) {
  122.     return (SYS_INVALID_ARG);
  123.   }
  124. #else
  125.   if (kernelAddress > vmBootEnd &&
  126.       kernelAddress < VMMACH_VIRT_CACHED_START) {
  127.     return(SYS_INVALID_ARG);
  128.   }
  129.   if (kernelAddress > vmMemEnd &&
  130.       kernelAddress < vmStackBaseAddr) {
  131.     return(SYS_INVALID_ARG);
  132.   }
  133.   if (kernelAddress > vmStackEndAddr &&
  134.       kernelAddress < vmBlockCacheBaseAddr) {
  135.     return(SYS_INVALID_ARG);
  136.   }
  137.   if (kernelAddress > vmBlockCacheEndAddr) {
  138.     return(SYS_INVALID_ARG);
  139.   }
  140. #endif
  141.   numPages = ((kernelAddress + bytesLeft - 1) >> VMMACH_PAGE_SHIFT) - 
  142.     (kernelAddress >> VMMACH_PAGE_SHIFT);
  143.   if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  144.     replyPtr->length = 0;
  145.     return(SYS_ARG_NOACCESS);
  146.   }
  147.   bytesInPage = vm_PageSize - (kernelAddress & (vm_PageSize-1));
  148.   if (bytesLeft < bytesInPage) {
  149.     bcopy(kernelAddress, bufPtr, bytesLeft);
  150.     replyPtr->length = readPtr->length;
  151.     return(SUCCESS);
  152.   }
  153.   bcopy(kernelAddress, bufPtr, bytesInPage);
  154.   bytesLeft -= bytesInPage;
  155.   bufPtr += vm_PageSize;
  156.   while (numPages > 0) {
  157.     if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  158.       replyPtr->length = 0;
  159.       return(SYS_ARG_NOACCESS);
  160.     }
  161.     if (bytesLeft < vm_PageSize) {
  162.       bcopy(kernelAddress, bufPtr, bytesLeft);
  163.       replyPtr->length = readPtr->length;
  164.       return(SUCCESS);
  165.     }
  166.     bcopy(kernelAddress, bufPtr, vm_PageSize);
  167.     bytesLeft -= vm_PageSize;
  168.     bufPtr += vm_PageSize;
  169.     numPages--;
  170.   }
  171.   replyPtr->length = readPtr->length;
  172.   return(SUCCESS);
  173. }
  174.  
  175.  
  176. /*
  177.  *----------------------------------------------------------------------
  178.  *
  179.  *  Dev_SmemWrite --
  180.  *
  181.  *    Writes if it can, and returns SUCCESS if it wrote.
  182.  *
  183.  * Results:
  184.  *    A standard Sprite return status.
  185.  *
  186.  * Side effects:
  187.  *    None.
  188.  *
  189.  *----------------------------------------------------------------------
  190.  */
  191. /*ARGSUSED*/
  192. ReturnStatus
  193. Dev_SmemWrite(devicePtr, writePtr, replyPtr)
  194.     Fs_Device *devicePtr;
  195.     Fs_IOParam    *writePtr;    /* Standard write parameter block */
  196.     Fs_IOReply    *replyPtr;    /* Return length and signal */
  197. {
  198.   int status, bytesLeft;
  199.   int kernelAddress;
  200.   int numPages, bytesInPage;
  201.   char *bufPtr;
  202.   StopInfo stopInfo;
  203.   Dbg_DumpBounds currentBounds;
  204.   
  205.   stopInfo.codeStart = (int)mach_CodeStart;
  206.   stopInfo.trapType = (mach_DebugState.causeReg & MACH_CR_EXC_CODE) >>
  207.     MACH_CR_EXC_CODE_SHIFT;
  208.   DebugToRegState(&mach_DebugState, &(stopInfo.regs));
  209.   currentBounds.pageSize = vm_PageSize;
  210.   currentBounds.stackSize = mach_KernStackSize;
  211.   currentBounds.kernelCodeStart = (unsigned int) mach_KernStart;
  212.   currentBounds.kernelCodeSize  =
  213.     (unsigned int) (vmBootEnd - mach_KernStart);
  214.   currentBounds.kernelDataStart  = VMMACH_VIRT_CACHED_START;
  215.   currentBounds.kernelDataSize   = (unsigned int)
  216.     (vmMemEnd - VMMACH_VIRT_CACHED_START);
  217.   currentBounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  218.   currentBounds.kernelStacksSize = (unsigned int)
  219.     (vmStackEndAddr - vmStackBaseAddr);
  220.   currentBounds.fileCacheStart   = (unsigned int)vmBlockCacheBaseAddr;
  221.   currentBounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr -
  222.                         vmBlockCacheBaseAddr);
  223.   kernelAddress = writePtr->offset;
  224.   bytesLeft = writePtr->length;
  225.   bufPtr = writePtr->buffer;
  226.  
  227.   /* Get part or all of stop info if requested. */
  228.   if (kernelAddress < sizeof(StopInfo)) {
  229.     if (bytesLeft + kernelAddress <= sizeof(StopInfo)) {
  230.       bcopy(writePtr->buffer, ((char *)&stopInfo) + kernelAddress, writePtr->length);
  231.       replyPtr->length = writePtr->length;
  232.       return(SUCCESS);
  233.     }
  234.     bcopy(writePtr->buffer, ((char *)&stopInfo) + kernelAddress, sizeof(StopInfo) - kernelAddress);
  235.     bytesLeft -= sizeof(StopInfo) - kernelAddress;
  236.     bufPtr += sizeof(StopInfo) - kernelAddress;
  237.     kernelAddress = sizeof(StopInfo);
  238.   }
  239.   
  240.   /* Get part or all of dump bounds if requested. */
  241.   if (kernelAddress < (sizeof(StopInfo) + sizeof(Dbg_DumpBounds))) {
  242.     if (bytesLeft + kernelAddress <= sizeof(StopInfo) + sizeof(Dbg_DumpBounds)) {
  243.       bcopy(bufPtr, ((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bytesLeft);
  244.       replyPtr->length = writePtr->length;
  245.       return(SUCCESS);
  246.     }
  247.     bcopy(bufPtr, ((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, sizeof(Dbg_DumpBounds));
  248.     bytesLeft -= sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  249.     bufPtr += sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
  250.     kernelAddress = sizeof(StopInfo) + sizeof(Dbg_DumpBounds);
  251.   }
  252.  
  253.   /* Set address to beginning of kernel memory. */
  254.   kernelAddress += mach_KernStart - (sizeof(StopInfo) + sizeof(Dbg_DumpBounds));
  255.  
  256.   /* Make sure offset is valid. */
  257. #ifdef NOGAP
  258.   if (kernelAddress > vmBootEnd) {
  259.     kernelAddress += VMMACH_VIRT_CACHED_START - vmBootEnd;
  260.   }
  261.   if (kernelAddress > vmMemEnd) {
  262.     kernelAddress += vmStackBaseAddr - vmMemEnd;
  263.   }
  264.   if (kernelAddress > vmStackEndAddr) {
  265.     kernelAddress += vmBlockCacheBaseAddr - vmStackEndAddr;
  266.   }
  267.   if (kernelAddress > vmBlockCacheEndAddr) {
  268.     return (SYS_INVALID_ARG);
  269.   }
  270. #else
  271.   if (kernelAddress > vmBootEnd &&
  272.       kernelAddress < VMMACH_VIRT_CACHED_START) {
  273.     return(SYS_INVALID_ARG);
  274.   }n
  275.   if (kernelAddress > vmMemEnd &&
  276.       kernelAddress < vmStackBaseAddr) {
  277.     return(SYS_INVALID_ARG);
  278.   }
  279.   if (kernelAddress > vmStackEndAddr &&
  280.       kernelAddress < vmBlockCacheBaseAddr) {
  281.     return(SYS_INVALID_ARG);
  282.   }
  283.   if (kernelAddress > vmBlockCacheEndAddr) {
  284.     return(SYS_INVALID_ARG);
  285.   }
  286. #endif
  287.   
  288.   /* Find number of pages that request spans. */
  289.   numPages = ((kernelAddress + bytesLeft - 1) >> VMMACH_PAGE_SHIFT) - 
  290.     (kernelAddress >> VMMACH_PAGE_SHIFT);
  291.   if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  292.     replyPtr->length = 0;
  293.     return(SYS_ARG_NOACCESS);
  294.   }
  295.   bytesInPage = vm_PageSize - (kernelAddress & (vm_PageSize-1));
  296.   if (bytesLeft < bytesInPage) {
  297.     bcopy(bufPtr, kernelAddress, bytesLeft);
  298.     replyPtr->length = writePtr->length;
  299.     return(SUCCESS);
  300.   }
  301.   bcopy(bufPtr, kernelAddress, bytesInPage);
  302.   bytesLeft -= bytesInPage;
  303.   bufPtr += vm_PageSize;
  304.  
  305.   /* Make each page accessible, if possible and copy it into 
  306.      return buffer. */
  307.   while (numPages > 0) {
  308.     if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
  309.       replyPtr->length = 0;
  310.       return(SYS_ARG_NOACCESS);
  311.     }
  312.     if (bytesLeft < vm_PageSize) {
  313.       bcopy(bufPtr, kernelAddress, bytesLeft);
  314.       replyPtr->length = writePtr->length;
  315.       return(SUCCESS);
  316.     }
  317.     bcopy(bufPtr, kernelAddress, vm_PageSize);
  318.     bytesLeft -= vm_PageSize;
  319.     bufPtr += vm_PageSize;
  320.     numPages--;
  321.   }
  322.   replyPtr->length = writePtr->length;
  323.   return(SUCCESS);
  324. }
  325.  
  326.  
  327. /*
  328.  *----------------------------------------------------------------------
  329.  *
  330.  * Dev_SmemIOControl --
  331.  *
  332.  *    This procedure handles IOControls for /dev/smem and other
  333.  *    devices.  It refuses all IOControls except for a few of
  334.  *    the generic ones, for which it does nothing.
  335.  *
  336.  * Results:
  337.  *    A standard Sprite return status.
  338.  *
  339.  * Side effects:
  340.  *    None.
  341.  *
  342.  *----------------------------------------------------------------------
  343.  */
  344.  
  345. /* ARGSUSED */
  346. ReturnStatus
  347. Dev_SmemIOControl(devicePtr, ioctlPtr, replyPtr)
  348.     Fs_Device            *devicePtr;
  349.     Fs_IOCParam        *ioctlPtr;
  350.     Fs_IOReply        *replyPtr;
  351. {
  352.     if ((ioctlPtr->command == IOC_GET_FLAGS)
  353.     || (ioctlPtr->command == IOC_SET_FLAGS)
  354.     || (ioctlPtr->command == IOC_SET_BITS)
  355.     || (ioctlPtr->command == IOC_CLEAR_BITS)
  356.     || (ioctlPtr->command == IOC_REPOSITION)) {
  357.     return SUCCESS;
  358.     }
  359.     return GEN_NOT_IMPLEMENTED;
  360. }
  361.  
  362. /*
  363.  *----------------------------------------------------------------------
  364.  *
  365.  * Dev_SmemSelect --
  366.  *
  367.  *    This procedure handles selects for /dev/smem and other
  368.  *    devices that are always ready.
  369.  *
  370.  * Results:
  371.  *    The device is indicated to be readable and writable.
  372.  *
  373.  * Side effects:
  374.  *    None.
  375.  *
  376.  *----------------------------------------------------------------------
  377.  */
  378.  
  379. /* ARGSUSED */
  380. ReturnStatus
  381. Dev_SmemSelect(devicePtr, readPtr, writePtr, exceptPtr)
  382.     Fs_Device    *devicePtr;    /* Ignored. */
  383.     int    *readPtr;        /* Read bit to clear if not readable */
  384.     int    *writePtr;        /* Write bit to clear if not readable */
  385.     int    *exceptPtr;        /* Except bit to clear if not readable */
  386. {
  387.     *exceptPtr = 0;
  388.     return(SUCCESS);
  389. }
  390.  
  391. /*
  392.  *----------------------------------------------------------------------
  393.  *
  394.  * DebugToRegState --
  395.  *
  396.  *      Converts a Mach_DebugState to Mach_RegState.
  397.  *
  398.  * Results:
  399.  *      None.
  400.  *
  401.  * Side effects:
  402.  *      None.
  403.  *
  404.  *----------------------------------------------------------------------
  405.  */
  406. static void
  407. DebugToRegState(debugPtr, regPtr)
  408.     Mach_DebugState     *debugPtr;
  409.     Mach_RegState       *regPtr;
  410. {
  411.     regPtr->pc = (Address) debugPtr->excPC;
  412.     bcopy((char *) debugPtr->regs, (char *) regPtr->regs,
  413.         MACH_NUM_GPRS * sizeof(int));
  414.     bcopy((char *) debugPtr->fpRegs, (char *) regPtr->fpRegs,
  415.         MACH_NUM_FPRS * sizeof(int));
  416.     regPtr->fpStatusReg = debugPtr->fpCSR;
  417.     regPtr->mfhi = debugPtr->multHi;
  418.     regPtr->mflo = debugPtr->multLo;
  419. }
  420.